<?php

#require_once("./classes/resize_image_helper.php");

// Raw Image Path
#$path = "./img/01.jpg";

/*
 * Load the image in the instance, but you can load the image after or reload
 * the image using $image->load_image($path);
 */
#$image = new Resize_image_helper($path);

/*
 *  Resize the image adjusting the width to 300px,
 *  the height still the same
 */
#$image->resize_width(300);

/*
 * Resize the image adjusting the height to 300px,
 * the width still the same
 */
#$image->resize_height(300);

/*
 *	At this point you have 3 images, the original image, other with the same name plus
 *  a suffix "_w300" result of the first transform, and other with the suffix "_h300"
 *  result of the second transform.
 *
 *  If you want changes applied to the original image and are cumulative
 *  use the second parameter OVERWRITE = TRUE
 */

/*
 *  Resize the image on both dimensions.
 *  Create a new image with original name and the suffix _w500_h250.
 *  You can use OVERWRITE = TRUE to apply the changes on the original image.
 */
#$image->resize_both(500, 250);

/*
 * Change the aspect ratio.
 * The first element refers to the height and the second to the weight.
 * You can use OVERWRITE = TRUE to apply the changes on the original image.
 *
 * The following aspects are the usual but you can use any you want.
 */

#$image->change_aspect_ratio("1:1");
#$image->change_aspect_ratio("4:3");
#$image->change_aspect_ratio("3:2");
#$image->change_aspect_ratio("16:9");
#$image->change_aspect_ratio("3:1");

/*
 * You can clear the memory manually if you believe necessary, otherwise the image
 * resource be destroyed on the __destruct method.
 */
#$image->free_image_mem();

?>
<?php
/*	Copyright (c) <2012><Martin San Juan>
 *	All rights reserved.
 *
 *	Redistribution and use in source and binary forms, with or without
 *	modification, are permitted provided that the following conditions
 *	are met:
 *	1. Redistributions of source code must retain the above copyright
 *	notice, this list of conditions and the following disclaimer.
 *	2. Redistributions in binary form must reproduce the above copyright
 *	notice, this list of conditions and the following disclaimer in the
 *	documentation and/or other materials provided with the distribution.
 *	3. Neither the name of copyright holders nor the names of its
 *	contributors may be used to endorse or promote products derived
 *	from this software without specific prior written permission.
 *
 *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *	PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
 *	BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *	POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Mart? San Juan<martin.sanjuan@gmail.com>
 * @license BSD
 * @package ResizeImageHelper
 * @version 1.0
 *
 */
class ResizeImageHelper
{
	/**
	 * Conversion Units allowed to size of File
	 * @var strign array $_units
	 */
	protected $_units = array("B", "KB", "MB", "GB");
	/**
	 * Allowed Extensions for the image resource
	 * @var string array $_allowed_extensions
	 */
	protected $_allowed_extensions = array("jpeg", "jpg", "png", "gif");
	/**
	 * Default JPG Quality
	 * @var int 1~100
	 */
	private $_jpg_quality = 100;
	/**
	 * Default PNG Compression
	 * @var int 1~9
	 */
	private $_png_compression = 0;
	/**
	 * Original width
	 * @var int
	 */
	private $_width;
	/**
	 * Original Height
	 * @var int
	 */
	private $_height;
	/**
	 * Original Aspect
	 * @var unknown_type
	 */
	private $_aspect;

	/**
	 * ["dirname"]  : Full folder path of image
	 * ["fullpath]  : Same as dirname but includes the filename and extension
	 * ["filename]  : Image name without extension
	 * ["extension] : Image extension
	 * ["filesize"] : Image filesize
	 * @var array
	 *
	 */
	private $file = array();
	/**
	 * Resource image.
	 * @var unknown_type
	 */
	protected $_resource;

	function __construct($src_path_img = NULL)
	{
		if(!empty($src_path_img)){
			$this->load_image($src_path_img);
		}

		$this->_reflex = new ReflectionClass('Resize_image_helper');
	}

	/**
	 *
	 * Verifies that the file extension is supported
	 * @param string $ext
	 * @return boolean
	 */
	private function _is_allowed_extension($ext)
	{
		try{
			if(empty($ext)){
				throw new Exception("Invalid Argument");
			}

			$ext = strtolower($ext);
		 	return in_array($ext, $this->_allowed_extensions);

		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Returns a value with two decimals from Megabyte.
	 * If the conversion is in the order of 1E-3 returns zero
	 * @param string
	 * @return int|float
	 */
	private function _convert_size($unit)
	{
		try{

			if(empty($unit)){
				throw new Exception("Invalid Argument");
			}

			switch($unit){
				case "B":{
					return $this->file["filesize"];
				}
				case "KB":{
					$size = floor($this->file["filesize"] / 1024 );
					return $size;
				}
				case "MB":{
					$size = round(
							($this->file["filesize"] / 1048576 ),
						 	2, PHP_ROUND_HALF_DOWN
						 );
					return $size;
				}
				case "GB":{
					$size = round(
								($this->file["filesize"] / 1073741824 ),
								2, PHP_ROUND_HALF_DOWN
							);
					return $size;
				}
			}
		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Assumes the existing resource and extension validates
	 * Generates a new image
	 * $output = NULL : the raw image stream will be outputted directly
	 * $output = filepath : the raw image will be saved in a file
	 *
	 * @param resource $container
	 * @param string $ext
	 * @param $output
	 */
	private function _sample($container, $ext, $output = NULL)
	{
		try{
			if(empty($container) || empty($ext)){
				throw new Exception("Invalid Argument");
			}

			$ext = strtolower($ext);
			switch($ext)
			{
				case "jpg":{
					$resample = imageJPEG(
									$container,
									$output,
									$this->_jpg_quality
									);
					break;
				}
				case "jpge":{
					$resample = imageJPEG(
									$container,
									$output,
									$this->_jpg_quality
									);
					break;
				}
				case "png":{
					$resample = imagepng(
									$container,
									$output,
									$this->_png_compression
									);
					break;
				}
				case "gif":{
					$resample = imagegif($container, $output);
				}
			}

			if(empty($resample)){
				throw new Exception("Cannot Render the Image");
			}

			return $resample;

		}catch(Extension $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Initializes an image
	 * @param string
	 */
	function load_image($src_path_image)
	{
		try{
			if(empty($src_path_image)){

				throw new Exception("Invalid Argument");
			}

			$foo = pathinfo($src_path_image);

			if(!isset($foo["extension"])){
				throw new Exception(
					"Could not retrieve information from the image"
				);
			}

			if(!$this->_is_allowed_extension($foo["extension"])){
				throw new Exception("Unsupported extension");
			}

			$this->file["fullpath"] = $src_path_image;
			$this->file["dirname"] = $foo["dirname"];
			$this->file["basename"] = $foo["basename"];
			$this->file["extension"] = strtoupper(
										$foo["extension"]
										);
			$this->file["filename"] = $foo["filename"];
			$this->file["filesize"] = filesize($src_path_image);

			switch($this->file["extension"]){

				case "JPEG":{
					$this->_resource = ImageCreateFromJPEG(
						$src_path_image
						);
					break;
				}

				case "JPG":{
					$this->_resource = ImageCreateFromJPEG(
						$src_path_image
						);
					break;
				}

				case "PNG":{
					$this->_resource = ImageCreateFromPNG(
						$src_path_image
						);
					break;
				}

				case "GIF":{
					$this->_resource = ImageCreateFromGIF(
						$src_path_image
						);
					break;
				}
			}

			if($this->_resource === FALSE){

				throw new Exception("Could not create the resource");
			}else{
				$this->_width = imagesx($this->_resource);
				// Get Original Image Width
				$this->_height = imagesy($this->_resource);
				// Get Original Image Height
				if(!empty($this->_width) && !empty($this->_height)){

					$this->aspect = round(
									($this->_width / $this->_height),
								 	2, PHP_ROUND_HALF_DOWN
								 );
					return true;
				}else{

					throw new Exception(
						"Could not recover the dimensions of the image"
					);
				}
			}
		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Convert the format of an image.
	 * $reload = true : Load the resulting image on the object
	 * @param string $ext
	 * @param boolena $reload
	 */
	function convert_as($ext, $reload = FALSE, $save_as_file = TRUE, $save_name = NULL)
	{
		try{
			if(empty($ext)){
				throw new Exception("Extension cannot be NULL");
			}

			if(empty($this->_resource)){
				throw new Exception("Resource is needed");
			}

			strtolower($ext);

			if($this->_is_allowed_extension($ext)){

				$temp_image = @imagecreatetruecolor($this->_width, $this->_height);
				@imagecopyresampled(
								$temp_image,
								$this->_resource, 0, 0, 0, 0,
								$this->_width, $this->_height,
								$this->_width, $this->_height
								);

				if($save_as_file){
					$output = $this->file["dirname"] . "/";

					if(!empty($save_name)){
						$output .= $save_name . "." . $ext;
					}
					else{
						$output .= $this->file["filename"] . "." . $ext;
					}
				}
				else{
					$output = NULL;
				}

				if($this->_sample($temp_image, $ext, $output)){

					if($reload === TRUE){
						return $this->load_image($output);
					}
					else{
						return true;
					}
				}
				else{
					throw new Exception("Cannot Render the Image");
				}
			}
			else{
				throw new Exception("Unsupported extension");
			}
		}catch(Exception $e){
			echo $e->getMessage();
		}
	}


	/**
	 * WARNING: The image can distort if you change the original aspect ratio.
	 * Is recommended use change_aspect_ratio($ratio)
	 * Resizes the image
	 *
	 * WARNING:
	 * If the $overwrite option is active the original image will be replace.
	 *
	 * $overwrite = TRUE: replace the original image
	 * $overwrite = FALSE (default): create a copy with the original
	 * name and suffix w{$width}h{$height}
	 *
	 * @param int $width
	 * @param int $height
	 * @param boolean $overwrite
	 * @return boolean
	 */
	function resize_both($width, $height, $overwrite = FALSE)
	{
		try{
			if(empty($width) || empty($height)){
				throw new Exception("Invalid arguments");
			}

			if(empty($this->_resource)){
				throw new Exception("Resource is needed");
			}
		}catch(Exception $e){
			echo $e->getMessage();
		}

		$temp_image = @imagecreatetruecolor($width, $height);
		@imagecopyresampled(
						$temp_image,
						$this->_resource, 0, 0, 0, 0,
						$width, $height, // Resize dimensions
						$this->_width, $this->_height // Original dimensions
						);

		if(!$overwrite){
			$output = "{$this->file["dirname"]}/{$this->file["filename"]}_w{$width}h{$height}.{$this->file["extension"]}";
		}
		else{
			$output = $this->file["fullpath"];
		}

		if($this->_sample($temp_image, $this->file["extension"], $output)){
			return TRUE;
		}else{
			return FALSE;
		}

	}

	/**
	 *
	 *
	 * Resize width of image
	 *
	 * $respect_proportion = TRUE :
	 * 		Adjusts the image width;
	 * 		Adjusts the image height based on the original aspect ratio
	 *
	 * $respect_proportion = FALSE:
	 * 		Adjusts the image width;
	 *
	 * WARNING:
	 * If the $overwrite option is active the original image will be replace.
	 *
	 * $overwrite = TRUE: replace the original image
	 * $overwrite = FALSE (default): create a copy with the original
	 * name and suffix h{$height}
	 *
	 * @param int $height
	 * @param boolean $overwrite
	 * @param boolean $respect_proportion
	 * @return boolean
	 */
	function resize_height($height, $overwrite = FALSE, $respect_proportion = TRUE)
	{
		try{
			if(empty($height)){
				throw new Exception("Invalid Argument");
			}

			if(empty($this->_resource)){
				throw new Exception("Resource is needed");
			}

			if($respect_proportion){
				$width = (int)($height * $this->aspect);
			}else{
				$width = $this->_width;
			}

			$temp_image = @imagecreatetruecolor($width, $height);
			@imagecopyresampled(
							$temp_image,
							$this->_resource, 0, 0, 0, 0,
							$width, $height, // Resize dimensions
							$this->_width, $this->_height // Original dimensions
							);


			if(!$overwrite){
				$output = "{$this->file["dirname"]}/{$this->file["filename"]}_h{$height}.{$this->file["extension"]}";
			}
			else{
				$output = $this->file["fullpath"];
			}

			if($this->_sample($temp_image, $this->file["extension"], $output)){
				return TRUE;
			}else{
				return FALSE;
			}

		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 *
	 * Resize height of image
	 *
	 * $respect_proportion = TRUE :
	 * 		Adjusts the image heigh;
	 * 		Adjusts the image width based on the original aspect ratio
	 *
	 * $respect_proportion = FALSE:
	 * 		Adjusts the image height
	 *
	 * WARNING:
	 * If the $overwrite option is active the original image will be replace.
	 *
	 * $overwrite = TRUE: replace the original image
	 * $overwrite = FALSE (default): create a copy with the original
	 * name and suffix w{$width}
	 *
	 * @param int $width
	 * @param boolean $width
	 * @param boolean $respect_proportion
	 * @return boolean
	 */
	function resize_width($width, $overwrite = FALSE, $respect_proportion = TRUE)
	{
		try{
			if(empty($width)){
				throw new Exception("Invalid Argument");
			}

			if(empty($this->_resource)){
				throw new Exception("Resource is needed");
			}

			if($respect_proportion){
				$height = (int)($width /  $this->aspect);
			}else{
				$height = $this->_height;
			}

			$temp_image = @imagecreatetruecolor($width, $height);
			@imagecopyresampled(
							$temp_image,
							$this->_resource, 0, 0, 0, 0,
							$width, $height, // Resize dimensions
							$this->_width, $this->_height // Original dimensions
							);

			if(!$overwrite){
				$output = "{$this->file["dirname"]}/{$this->file["filename"]}_w{$height}.{$this->file["extension"]}";
			}
			else{
				$output = $this->file["fullpath"];
			}

			if($this->_sample($temp_image, $this->file["extension"], $output)){
				return TRUE;
			}else{
				return FALSE;
			}

		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Adjust height to meet the proportion
	 * @param string $ratio
	 * @return boolean
	 */
	function change_aspect_ratio($ratio, $overwrite = FALSE)
	{
		try{
			if(empty($ratio)){
				throw new Exception("Invalid Argument");
			}

			$ratio = explode(":", $ratio);

			if(!is_numeric($ratio[0]) ||  !is_numeric($ratio[1])){
			    throw new Exception("Unsupported Ratio");
			}

			$height = (int)( $this->_width / ($ratio[0] / $ratio[1]));

			return $this->resize_both($this->_width, $height, $overwrite);

		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Destroy the image resource
	 * @return boolean
	 */
	function free_image_mem()
	{
		if(!empty($this->_resource)){
			return @imagedestroy($this->_resource);
		}else{
			return true;
		}
	}

	/**
	 * Returns the width if it exists, false otherwise
	 * @return int|FALSE
	 */
	function get_width()
	{
		if(empty($this->_width)){
			return false;
		}else{
			return $this->_width;
		}
	}

	/**
	 * Returns the heigth if it exists, false otherwise
	 * @return int|FALSE
	 */
	function get_height()
	{
		if(empty($this->_height)){
			return false;
		}else{
			return $this->_height;
		}
	}

	/**
	 * Returns the aspect if it exists, false otherwise
	 * @return float|FALSE
	 */
	function get_aspect()
	{
		if(empty($this->aspect)){
			return false;
		}else{
			return $this->aspect;
		}
	}

	/**
	 * Returns the file array if it exists, false otherwise
	 * @return array|FALSE
	 */
	function get_fileinfo()
	{
		if(empty($this->file)){
			return false;
		}else{
			return $this->file;
		}
	}

	/**
	 * Returns the dirname of a image, false otherwise
	 * @return string|FALSE
	 */
	function get_dirname()
	{
		if(!empty($this->file["dirname"])){
			return $this->file["dirname"];
		}else{
			return false;
		}
	}

	/**
	 * Returns the fullpath of a image, false otherwise
	 * @return string|FALSE
	 */
	function get_fullpath()
	{
		if(!empty($this->file["fullpath"])){
			return $this->file["fullpath"];
		}else{
			return false;
		}
	}

	/**
	 * Returns the filename of a image, false otherwise
	 * @return string|FALSE
	 */
	function get_filename()
	{
		if(!empty($this->file["filename"])){
			return $this->file["filename"];
		}else{
			return false;
		}
	}

	/**
	 * Returns the extension of a image, false otherwise
	 * @return string|FALSE
	 */
	function get_extension()
	{
		if(!empty($this->file["extension"])){
		    $ext = strtoupper($this->file["extension"]);
			return $ext;
		}else{
			return false;
		}
	}

	/**
	 * Retrieves the file size
	 * @param string [optional]
	 */
	function get_filesize($unit = "B")
	{
		try{
			if(empty($unit)){
				throw new Exception("Invalid Argument");
			}

			$unit = strtoupper($unit);

			if(in_array($unit, $this->_units)){

				return $this->_convert_size($unit);
			}
		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Return jpg_quality used to sample
	 * @return int
	 */
	function get_jpg_quality()
	{
		return $this->_jpg_quality;
	}


	/**
	 * Set jpg Quality used to sample
	 * @param int $quality
	 */
	function set_jpg_quality($quality)
	{
		try{

			if(isset($quality) && $quality === 0){
				$this->_jpg_quality = 0;
				return true;
			}

			if(empty($quality)){
				throw new Exception("Invalid Argument - Accepted: (int)0~100");
			}

			if($quality<1 || $quality>100){
				throw new Exception(
							"Invalid value to JPG quality - Accepted: (int)0~100"
							);
			}

			$this->_jpg_quality = $quality;

		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	/**
	 * Return PNG compression used to sample
	 * @return int
	 */
	function get_png_compression()
	{
		return $this->_png_compression;
	}

	/**
	 * Set PNG compression used to sample
	 * @param int $compression
	 * @return boolean
	 */
	function set_png_compression($compression)
	{
		try{
			if(isset($compression) && $compression === 0){
				$this->_png_compression = 0;
				return true;
			}

			if(empty($compression)){
				throw new Exception("Invalid Argument - Accepted: (int)1~9");
			}

			if($compression<1 || $compression>9){
				throw new Exception(
						"Invalid value to PNG compression - Accepted: (int)1~9"
						);
			}

			$this->_png_compression = (int)$compression;
			return true;
		}catch(Exception $e){
			echo $e->getMessage();
		}
	}

	function __destruct()
	{
		$this->free_image_mem();
	}
}